package com.yikome.promotion.service;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.yikome.common.CommonService;
import com.yikome.promotion.entity.FullReduction;
import com.yikome.promotion.enums.FullReductionStatus;
import com.yikome.promotion.repository.FullReductionRepository;
import com.yikome.promotion.request.FullReductionRequest;
import com.yikome.promotion.response.FullReductionResponse;
import com.yikome.promotion.response.ShopFullReductionResponse;
import com.yikome.shop.entity.Shop;
import com.yikome.shop.repository.ShopRepository;
import com.yikome.utils.BeanUtils;
import com.yikome.utils.NamedParameterJdbcUtils;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;

@Service
public class FullReductionService extends CommonService<FullReduction, Long> {

	@Autowired
	private FullReductionRepository everyFullReductionRepository ;
	
	@Autowired
	private ShopRepository shopRepository ;
	
	@Autowired
	private NamedParameterJdbcTemplate jdbcTemplate ;
	
	public Page<FullReductionResponse> findFullReduction(FullReductionRequest fullReductionRequest, Pageable pageable) {
	
		//TODO 在这里作SQL更新处理
		Date nowTime = Calendar.getInstance(TimeZone.getTimeZone("+8")).getTime();
		String updateSQL = "UPDATE pro_full_reduction SET pro_full_reduction.status = :invalidStatus WHERE pro_full_reduction.yn = 1 AND pro_full_reduction.status <= :activeStatus AND pro_full_reduction.end_time <= :nowTime" ; 
		
		jdbcTemplate.update(updateSQL, ImmutableMap.of("invalidStatus", FullReductionStatus.INVALID.getStatus(), "activeStatus", FullReductionStatus.ACTIVE.getStatus(), "nowTime", nowTime));
		
		String contentSQL = "SELECT pro_full_reduction.* , s_shop.name shop_name \n" + 
							"FROM pro_full_reduction \n" + 
							"	LEFT JOIN s_shop ON (pro_full_reduction.shop_id = s_shop.id) \n" + 
							"WHERE pro_full_reduction.yn = 1 \n" ; 
		
		StringBuilder paramSQL = new StringBuilder("");
		Map<String , Object> paramMap = new HashMap<>();
		
		if(fullReductionRequest.getShopId() != null) {
			paramSQL.append("AND pro_full_reduction.shop_id = :shopId \n");
			paramMap.put("shopId", fullReductionRequest.getShopId());
		}
		if(fullReductionRequest.getStatus() != null) {
			paramSQL.append("AND pro_full_reduction.status = :status \n");
			paramMap.put("status", fullReductionRequest.getStatus());
		}
		if(StrUtil.isNotBlank(fullReductionRequest.getPromotionName())) {
			paramSQL.append("AND pro_full_reduction.promotion_name like :promotionName \n");
			paramMap.put("promotionName", StrUtil.wrap(fullReductionRequest.getPromotionName().trim(), "%"));
		}
		
		String orderSQL = NamedParameterJdbcUtils.findOrderSQL(pageable);
    	String pageSQL = NamedParameterJdbcUtils.findPageSQL(pageable);
    	
    	List<FullReductionResponse> everyFullReductionResponses = jdbcTemplate.query(contentSQL + paramSQL + orderSQL + pageSQL , paramMap, new BeanPropertyRowMapper<>(FullReductionResponse.class));
    	
    	for (FullReductionResponse everyFullReductionResponse : everyFullReductionResponses) {
    		everyFullReductionResponse.setStatusName(FullReductionStatus.byStatus(everyFullReductionResponse.getStatus()).getStatusName());
		}
    	
    	Long total = jdbcTemplate.queryForObject("SELECT COUNT(1) FROM (" + contentSQL + paramSQL + ") T", paramMap, Long.class);

        return new PageImpl<>(everyFullReductionResponses, pageable, total);
	} 
	
	public List<ShopFullReductionResponse> findShopFullReductionResponse(Long shopId) {
		
		Date nowTime = Calendar.getInstance(TimeZone.getTimeZone("+8")).getTime();
		
		String contentSQL = "SELECT pro_full_reduction.*, pro_full_reduction.id promotion_id FROM pro_full_reduction \n" + 
							"WHERE pro_full_reduction.yn = 1 \n" ; 
		
		StringBuilder paramSQL = new StringBuilder("");
		Map<String , Object> paramMap = new HashMap<>();
		
		paramSQL.append("AND pro_full_reduction.status = :status \n");
		paramMap.put("status", FullReductionStatus.ACTIVE.getStatus());
		
		paramSQL.append("AND pro_full_reduction.begain_time <= :nowTime AND pro_full_reduction.end_time > :nowTime \n");
		paramMap.put("nowTime", nowTime);
		
		paramSQL.append("AND pro_full_reduction.shop_id = :shopId \n");
		paramMap.put("shopId", shopId);
		
		String orderSQL = "ORDER BY pro_full_reduction.full_value ASC \n" ;
		
		return jdbcTemplate.query(contentSQL + paramSQL + orderSQL, paramMap, new BeanPropertyRowMapper<>(ShopFullReductionResponse.class));
	}
	
	public List<ShopFullReductionResponse> findShopFullReductionResponse(Long shopId, BigDecimal cartPrice) {
		
		Date nowTime = Calendar.getInstance(TimeZone.getTimeZone("+8")).getTime();
		
		String contentSQL = "SELECT pro_full_reduction.*, pro_full_reduction.id promotion_id FROM pro_full_reduction \n" + 
							"WHERE pro_full_reduction.yn = 1 \n" ; 
		
		StringBuilder paramSQL = new StringBuilder("");
		Map<String , Object> paramMap = new HashMap<>();
		
		paramSQL.append("AND pro_full_reduction.status = :status \n");
		paramMap.put("status", FullReductionStatus.ACTIVE.getStatus());
		
		paramSQL.append("AND pro_full_reduction.begain_time <= :nowTime AND pro_full_reduction.end_time > :nowTime \n");
		paramMap.put("nowTime", nowTime);
		
		paramSQL.append("AND pro_full_reduction.shop_id = :shopId \n");
		paramMap.put("shopId", shopId);
		
		paramSQL.append("AND pro_full_reduction.full_value <= :cartPrice \n");
		paramMap.put("cartPrice", cartPrice);
		
		String orderSQL = "ORDER BY pro_full_reduction.full_value DESC \n" ;
		
		String pageSQL = "LIMIT 1 \n" ;
		
		return jdbcTemplate.query(contentSQL + paramSQL + orderSQL + pageSQL, paramMap, new BeanPropertyRowMapper<>(ShopFullReductionResponse.class));
	}

	@Transactional
	public FullReduction persistFullReduction(FullReduction fullReductionRequest) {
		
		Shop shop = shopRepository.findShop(fullReductionRequest.getShopId());
		Preconditions.checkArgument(shop != null, "商城不存在...");
		
		if(fullReductionRequest.getId() != null) {
			FullReduction source = everyFullReductionRepository.findFullReduction(fullReductionRequest.getId());
			
			Preconditions.checkArgument(source != null , "要修改的数据不存在...");
			Preconditions.checkArgument(source.getStatus() != FullReductionStatus.ACTIVE.getStatus(), "运行中的活动不允许修改...");
			
			BeanUtils.copyProperties(fullReductionRequest, source, "id" , "status" , "yn");
			
			return everyFullReductionRepository.save(source);
			
		}
		
		fullReductionRequest.setStatus(FullReductionStatus.CREATE.getStatus());
		FullReduction fullReduction = everyFullReductionRepository.save(fullReductionRequest);
		
		fullReductionRequest.setPromotionCode("MJ-" + RandomUtil.randomStringUpper(6) + "-" + fullReductionRequest.getId());
		everyFullReductionRepository.save(fullReductionRequest);
		return fullReduction ;
	}
	
	@Transactional
	public void deleteFullReduction(Long fullReductionId) {
		
		FullReduction everyFullReduction = everyFullReductionRepository.findFullReduction(fullReductionId);
		Preconditions.checkArgument(everyFullReduction != null , "要删除的数据不存在...");
		
		Preconditions.checkArgument(everyFullReduction.getStatus() == FullReductionStatus.CREATE.getStatus(), "仅新增活动允许删除...");
		
		everyFullReduction.setYn(0);
		
		everyFullReductionRepository.save(everyFullReduction) ; 
	}

	@Transactional
	public FullReduction upFullReduction(Long fullReductionId) {
		
		FullReduction everyFullReduction = everyFullReductionRepository.findFullReduction(fullReductionId);
		Preconditions.checkArgument(everyFullReduction != null , "数据不存在...");
		
		Preconditions.checkArgument(everyFullReduction.getStatus() != FullReductionStatus.ACTIVE.getStatus(), "状态不允许删除...");
		
		Date nowTime = Calendar.getInstance(TimeZone.getTimeZone("+8")).getTime();
		Preconditions.checkArgument(nowTime.before(everyFullReduction.getEndTime()), "活动已过期,不能上线...");
		
		everyFullReduction.setStatus(FullReductionStatus.ACTIVE.getStatus());
		
		return everyFullReductionRepository.save(everyFullReduction) ; 
		
	}

	@Transactional
	public FullReduction downFullReduction(Long fullReductionId) {

		FullReduction everyFullReduction = everyFullReductionRepository.findFullReduction(fullReductionId);
		Preconditions.checkArgument(everyFullReduction != null , "数据不存在...");
		
		Preconditions.checkArgument(everyFullReduction.getStatus() == FullReductionStatus.ACTIVE.getStatus(), "状态不允许删除...");
		
		everyFullReduction.setStatus(FullReductionStatus.INVALID.getStatus());
		
		return everyFullReductionRepository.save(everyFullReduction) ; 
	}
}
